#! /usr/bin/python
# -*- coding: utf-8 -*-
#
# Universidad Simón Bolívar
# Ingeniería de la Computación
# Traductores e Interpretadores (CI-3725)
# Septiembre - Diciembre 2011
#
# Proyecto 2: Lexer y Parser
#
# Autores:
# César Hernández  (06-39724)  <cesrafa@gmail.com>
# Daniel Valera    (07-41725)  <danielvaleradp@gmail.com>

import ply.yacc as yacc
from lex import tokens

DEBUG = True

precedence = (

    ('right', 'UMINUS'), 
    ('left', 'PLUS', 'MINUS'),
    ('left', 'MULT', 'DIV')
)

def p_mark(p):
    'mark : LBRACE MOD mark_body MOD RBRACE'
    print "hola !!!!!!!!!!!!!!!!!!"

def p_mark_body(p):
    'mark_body : mark_type definition'

def p_mark_type_exit(p):
    'mark_type : EQUAL' 

def p_mark_type_normal(p):
    'mark_type : empty'

def p_definition_inductive(p):
    'definition : many_def '

def p_definition_basecase(p):
    'definition :  expression'

def p_many_def(p):
    'many_def : VAR COLON type COLON EQUAL expression'
    
def p_many_def2(p):
    'many_def : VAR COLON type COMMA many_def COMMA expression'

def p_type_string(p):
    'type : STRING'

def p_type_int(p):
    'type : INT' 

def p_type_list_string(p):
    'type : LIST OF STRING'
def p_type_list_int(p):
    'type : LIST OF INT'
def p_type_table(p):
    'type : TABLE'

def p_basic_types_string(p):
    'basic_types : string' 

def p_basic_types_int(p):
    'basic_types : integer'

def p_integer_positive(p):
    'integer : NUMBER '

def p_integer_negative(p):    
    'integer : MINUS NUMBER %prec UMINUS'
    
def p_string(p):
    'string : TEXT'

def p_list(p):
    'list : LBRACKET list_types RBRACKET'

def p_list_types_normal(p):
    'list_types : normal_list'

def p_list_types_comprehension(p):    
    'list_types : comprehension_list'
    
def p_normal_list_inductive(p):
    'normal_list : normal_list COMMA basic_types'
        
def p_normal_list_basecase(p):
    'normal_list : basic_types'
def p_comprehension_list(p):
    'comprehension_list : MOD VAR COLON list COLON expression MOD'
        
def p_table(p):
    'table : NEW TABLE LBRACKET integer RBRACKET WHERE tab_elems'

def p_tab_elems_basecase(p):
    'tab_elems : VAR COLON basic_types COLON EQUAL expression'
    
def p_tab_elems_inductive(p):
    'tab_elems : tab_elems COMMA VAR COLON basic_types COLON EQUAL expression'

def p_numeric_var(p):
    'numeric : VAR '

def p_numeric_integer(p):
    'numeric : integer '

def p_operator_arit(p):
    'operator : arit_operator'
def p_operator_bool(p):
    'operator : bool_operator'
    
def p_arit(p):
    'arit : numeric arit_operator numeric'

def p_arit_operator_plus(p):
    'arit_operator : PLUS '
    
def p_arit_operator_minus(p):
    'arit_operator :  MINUS'
    
def p_arit_operator_mult(p):
    'arit_operator : MULT'
    
def p_arit_operator_div(p):
    'arit_operator : DIV '
    
def p_arit_operator_power(p):
    'arit_operator : POWER'
    
def p_arit_operator_mod(p):
    'arit_operator : MOD'
    
def p_concat_str_str(p):
    'concat : string PLUS string '
    
def p_concat_list_list(p):
    'concat : list PLUS list'
def p_concat_list_str(p):
    'concat : list PLUS string'
def p_concat_str_list(p):
    'concat : string PLUS list'
            
def p_concat_str_int(p):
    'concat : string PLUS integer'
def p_concat_int_str(p):
    'concat : integer PLUS string'
            
def p_list_access(p):
    'list_access : VAR LBRACKET expression RBRACKET'

def p_table_access(p):
    'table_access : VAR LBRACKET expression RBRACKET'

def p_quantifier(p):
    'quantifier : LBRACKET MOD operator COLON VAR COLON expression MOD RBRACKET'

def p_selection(p):
    'selection : IF condition THEN expression ELSE expression'

def p_condition_basecase(p):
    'condition : condition bool_operator boolean'
    
def p_condition_inductive(p):
    'condition : boolean'
                
def p_comparison_equal(p):
    'comparison : EQUAL '
def p_comparison_notequal(p):
    'comparison : NOTEQUAL'
    
def p_comparison_greater(p):
    'comparison : GREATER '
def p_comparison_less(p):
    'comparison : LESS '
def p_comparison_greaterequal(p):
    'comparison : GREATEREQUAL '
    
def p_comparison_lessequal(p):
    'comparison : LESSEQUAL'
    
def p_boolean(p):
    'boolean : integer comparison integer'

def p_bool_operator_and(p):
    'bool_operator : AND '
def p_bool_operator_or(p):   
    'bool_operator : OR '
def p_bool_operator_neg(p):
    'bool_operator : NEG'
    
def p_followby(p):
    'followby : expression FBY expression'

def p_triggeredby(p):
    'triggeredby : expression TBY expression'

def p_len(p):
    'len : LEN LPAREN expression RPAREN'

def p_input(p):
    'input : INPUT'

def p_range(p):
    'range : RANGE LPAREN expression COMMA expression RPAREN'

#Expresiones

def p_expression_var(p):
    'expression : VAR'
def p_expression_int(p): 
    'expression : integer' 
def p_expression_str(p):
    'expression : string' 
def p_expression_list(p):
    'expression : list' 
def p_expression_table(p):
    'expression : table'
def p_expression_arit(p):
    'expression : arit' 
def p_expression_concat(p):
    'expression : concat' 
def p_expression_listaccess(p):
    'expression : list_access' 
def p_expression_tableaccess(p):
    'expression : table_access'
def p_expression_quantifier(p):
    'expression : quantifier' 
def p_expression_selection(p):
    'expression : selection' 
def p_expression_followby(p):
    'expression : followby' 
def p_expression_triggeredby(p):
    'expression : triggeredby'
def p_expression_len(p):
    'expression : len' 
def p_expression_range(p):
    'expression : range' 
def p_expression_input(p):
    'expression : input'

def p_empty(p):
    'empty :'
    pass
    
def p_error(p):
    print "Syntax error!! ",p

yacc.yacc()
